package com.ssy.jt808.gateway.application.endpoint;

import com.ssy.jt808.gateway.application.service.FileService;
import com.ssy.jt808.gateway.application.service.TerminalAppService;
import com.ssy.jt808.gateway.domain.pojo.TerminalInfo;
import com.ssy.jt808.gateway.infrastructure.enums.SessionAttribute;
import com.ssy.jt808.protocol.basics.JTMessage;
import com.ssy.jt808.protocol.commons.JT808;
import com.ssy.jt808.protocol.t808.*;
import com.ssy.netmc.core.annotation.Async;
import com.ssy.netmc.core.annotation.AsyncBatch;
import com.ssy.netmc.core.annotation.Endpoint;
import com.ssy.netmc.core.annotation.Mapping;
import com.ssy.netmc.session.Session;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Objects;

/**
 * @author wangzezhou
 */
@Slf4j
@Endpoint
@Component
public class JT808Endpoint{

  @Autowired
  private TerminalAppService terminalStatusService;

  @Autowired
  private FileService fileService;


  @Mapping(types=JT808.终端通用应答, desc="终端通用应答")
  public Object T0001( T8001 message, Session session ){
    session.response(message);
    return null;
  }

  @Mapping(types=JT808.终端心跳, desc="终端心跳")
  public void T0002( JTMessage message, Session session ){
  }

  @Mapping(types=JT808.终端注销, desc="终端注销")
  public void T0003( JTMessage message, Session session ){
    session.invalidate();
  }

  @Mapping(types=JT808.查询服务器时间, desc="查询服务器时间")
  public T8004 T0004( JTMessage message, Session session ){
    return new T8004(LocalDateTime.now(ZoneOffset.UTC));
  }

  @Mapping(types=JT808.终端补传分包请求, desc="终端补传分包请求")
  public void T8003( T8003 message, Session session ){
  }

  @Mapping(types=JT808.终端注册, desc="终端注册")
  public T8100 T0100( T0100 message, Session session ){

    T8100 result = new T8100();

    TerminalInfo terminalInfo = SessionAttribute.doGetTerminalInfo(session);
    terminalInfo.setPhoneNo(message.getClientId());

    String token = terminalStatusService.onOnline(terminalInfo);

    terminalInfo.setProtocolVersion(message.getProtocolVersion());
    session.register(message);

    result.setToken(token);
    result.setResponseSerialNo(message.getSerialNo());
    result.setResultCode(T8100.Success);
    return result;
  }

  @Mapping(types=JT808.终端鉴权, desc="终端鉴权")
  public T8001 T0102( T0102 message, Session session ){

    T8001 result = new T8001();
    result.copyIdVersionProtocol(message);
    result.setResponseSerialNo(message.getSerialNo());
    result.setResponseMessageId(message.getMessageId());
    if( session.isRegistered() ){
      if( Objects.equals(message.getClientId(), session.getClientId()) ){
        session.register(message);
        result.setResultCode(T8001.Success);
        return result;
      }
    }

    TerminalInfo terminalInfo = terminalStatusService.onVerifyToken(message.getClientId(), message.getToken());
    terminalInfo.setProtocolVersion(message.getProtocolVersion());

    // 在会话上下文中保存终端信息
    SessionAttribute.setTerminalInfo(session, terminalInfo);

    session.register(message);
    result.setResultCode(T8001.Success);
    return result;
  }

  @Mapping(types=JT808.查询终端参数应答, desc="查询终端参数应答")
  public void T0104( T0104 message, Session session ){
    session.response(message);
  }

  @Mapping(types=JT808.查询终端属性应答, desc="查询终端属性应答")
  public void T0107( T0107 message, Session session ){
    session.response(message);
  }

  @Mapping(types=JT808.终端升级结果通知, desc="终端升级结果通知")
  public void T0108( T0108 message, Session session ){
  }

  /**
   * 异步批量处理
   * poolSize：参考数据库CPU核心数量
   * maxElements：最大累积4000条记录处理一次
   * maxWait：最大等待时间1秒
   */
  @AsyncBatch(poolSize=2, maxElements=100, maxWait=10000)
  @Mapping(types=JT808.位置信息汇报, desc="位置信息汇报")
  public void T0200( List<T0200> t0200s ){
    terminalStatusService.onLocation(t0200s);
  }

  @Mapping(types=JT808.定位数据批量上传, desc="定位数据批量上传")
  public void T0704( T0704 t0704, Session session ){
    terminalStatusService.onLocationBackoff(t0704);
  }

  @Mapping(types={ JT808.位置信息查询应答, JT808.车辆控制应答 }, desc="位置信息查询应答/车辆控制应答")
  public void T0201_0500( T0201_0500 message, Session session ){
    session.response(message);
  }

  @Mapping(types=JT808.事件报告, desc="事件报告")
  public void T0301( T0301 message, Session session ){
  }

  @Mapping(types=JT808.提问应答, desc="提问应答")
  public void T0302( T0302 message, Session session ){
  }

  @Mapping(types=JT808.信息点播_取消, desc="信息点播/取消")
  public void T0303( T0303 message, Session session ){
  }

  @Mapping(types=JT808.查询区域或线路数据应答, desc="查询区域或线路数据应答")
  public void T0608( T0608 message, Session session ){
    session.response(message);
  }

  @Mapping(types=JT808.行驶记录数据上传, desc="行驶记录仪数据上传")
  public void T0700( T0700 message, Session session ){
    session.response(message);
  }

  @Mapping(types=JT808.电子运单上报, desc="电子运单上报")
  public void T0701( JTMessage message, Session session ){
  }

  @Mapping(types=JT808.驾驶员身份信息采集上报, desc="驾驶员身份信息采集上报")
  public void T0702( T0702 message, Session session ){
    session.response(message);
  }

  @Mapping(types=JT808.CAN总线数据上传, desc="CAN总线数据上传")
  public void T0705( T0705 message, Session session ){
  }

  @Mapping(types=JT808.多媒体事件信息上传, desc="多媒体事件信息上传")
  public void T0800( T0800 message, Session session ){
  }

  @Async
  @Mapping(types=JT808.多媒体数据上传, desc="多媒体数据上传")
  public JTMessage T0801( T0801 message, Session session ){
    if( message.getPacket() == null ){
      T8001 result = new T8001();
      result.copyIdVersionProtocol(message);
      result.setMessageId(JT808.平台通用应答);
      result.setSerialNo(session.nextSerialNo());

      result.setResponseSerialNo(message.getSerialNo());
      result.setResponseMessageId(message.getMessageId());
      result.setResultCode(T8001.Success);
      return result;
    }
    fileService.saveMediaFile(message);
    T8800 result = new T8800();
    result.setMediaId(message.getId());
    return result;
  }

  @Mapping(types=JT808.存储多媒体数据检索应答, desc="存储多媒体数据检索应答")
  public void T0802( T0802 message, Session session ){
    session.response(message);
  }

  @Mapping(types=JT808.摄像头立即拍摄命令应答, desc="摄像头立即拍摄命令应答")
  public void T0805( T0805 message, Session session ){
    session.response(message);
  }

  @Mapping(types=JT808.数据上行透传, desc="数据上行透传")
  public void T0900( T0900 message, Session session ){
  }

  @Mapping(types=JT808.数据压缩上报, desc="数据压缩上报")
  public void T0901( T0901 message, Session session ){
  }

  @Mapping(types=JT808.终端RSA公钥, desc="终端RSA公钥")
  public void T0A00( com.ssy.jt808.gateway.adapter.protocol.T0A00_8A00 message, Session session ){
    session.response(message);
  }
}